package com.mydomain.Bodega;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.math.*;
import javax.ejb.Remove;
import javax.ejb.SessionContext;
import javax.ejb.Stateful;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.model.SelectItem;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.Transactional;
import org.jboss.seam.contexts.Context;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.faces.FacesMessages;

import com.mydomain.Bodega.PerfilListado.GadgetTypeConverter;

@Stateful
@Name("grupoListado")
@Scope(ScopeType.EVENT)
public class GrupoListado implements IGrupoListado {

	// All gadget types pulled from the database
	private List<InvGrupo> mInvGrupo;

	// All gadget types pulled from the database
	private List<Subdepartamento> mBodega;

	// All gadget types pulled from the database
	private List<Departamento> mDepartamento;

	// All gadget types pulled from the database
	private List<InvProveedor> mInvProveedor;

	// All gadget types pulled from the database
	private List<InvCliente> mInvCliente;

	// Map to be used for select lists in the UI
	private Map<String, InvGrupo> mInvGrupoMap;

	// All gadget types pulled from the database
	private List<AuxInvItem> mAuxInvItem;

	@In(value = "#{row.auxInvItem}", required = false)
	private String auxInvItem;

	private List<InvItemStock> mAuxInvItemEgreso;

	// Map to be used for select lists in the UI
	private Map<String, InvItemStock> mInvItemMap;

	private BigDecimal precio;

	@In(value = "#{row.gruCodigo}", required = false)
	private String gruCodigo;

	@In(value = "#{rowing.gruCodigo}", required = false)
	private String gruCodigoing;

	@In(value = "#{invAjusteHome.instance.ajuGrupo}", required = false)
	private String ajuGrupo = "";

	@In(value = "#{row.auxInvItem}", required = false)
	private String auxCodigo;

	@In(value = "#{invAjusteHome.instance.auxsubDep}", required = false)
	private String subdepartamento;

	@In(value = "#{row.egiCantidad}", required = false)
	private BigDecimal egiCantidad;

	@In(value = "#{rowing.iniCantidad}", required = false)
	private BigDecimal iniCantidad;

	@In(value = "#{auditoria.manualGrupo}", required = false)
	private String reportemanualGrupo;

	public BigDecimal getIniCantidad() {
		return iniCantidad;
	}

	public void setIniCantidad(BigDecimal iniCantidad) {
		this.iniCantidad = iniCantidad;
	}

	@PersistenceContext
	EntityManager em;

	/**
	 * When this bean is created, load up the types and populate the internal
	 * map
	 */
	@Create
	public void loadInvGrupo() {
		// Load up the types from the database, ordering them by label
		mInvGrupo = em.createQuery("select gt from InvGrupo gt")
				.getResultList();

		// Convert the list into a map. We use a TreeMap in order
		// to preserve the ordering we asked for i
		// above.
		Map<String, InvGrupo> results = new TreeMap<String, InvGrupo>();

		for (InvGrupo us : mInvGrupo) {
			results.put(us.getGruNombre(), us);
		}

		mInvGrupoMap = results;
	}

	public Collection<SelectItem> getGrupoSelectItems() {
		Collection<SelectItem> invGrupo = new ArrayList<SelectItem>();
		Integer contar = 0;
		mInvGrupo = em
				.createQuery(
						"select gt from InvGrupo gt where gt.gruEstado=true order by gt.gruNombre")
				.getResultList();
		invGrupo.add(new SelectItem("", ""));
		for (InvGrupo us : mInvGrupo) {
			invGrupo.add(new SelectItem(us.getGruCodigo(), us.getGruNombre()));
			contar++;
		}
		return invGrupo;
	}

	public Collection<SelectItem> getBodegaSelectItems() {
		Collection<SelectItem> subdepartamento = new ArrayList<SelectItem>();
		Integer contar = 0;
		mBodega = em.createQuery("select s from Subdepartamento s ")
				.getResultList();
		subdepartamento.add(new SelectItem("", ""));
		for (Subdepartamento us : mBodega) {
			subdepartamento.add(new SelectItem(us.getSubdepCodigo(), us
					.getDescripcion()));
			contar++;
		}
		return subdepartamento;
	}

	public Collection<SelectItem> getListaItemsSelectItems() {
		Collection<SelectItem> invAuxInvItem = new ArrayList<SelectItem>();

		if (ajuGrupo != null && ajuGrupo != "") {
			gruCodigoing = ajuGrupo;
		}
		if (gruCodigoing != null) {
			System.out.println("Datos:  " + gruCodigoing);
			mAuxInvItem = em
					.createQuery(
							"select i  from AuxInvItem i join i.invGrupo g where g.gruCodigo = :grupo and i.iteEstado=true order by i.iteNombre")
					.setParameter("grupo", this.gruCodigoing).getResultList();
			for (AuxInvItem us : mAuxInvItem) {
				invAuxInvItem.add(new SelectItem(us.getIteCodigo(), us
						.getIteNombre()));
			}
			return invAuxInvItem;
		} else {

			return new ArrayList<SelectItem>();
		}
	}

	public Collection<SelectItem> getListaItemsSelect() {
		Collection<SelectItem> invAuxInvItem = new ArrayList<SelectItem>();

		if (reportemanualGrupo != null) {
			System.out.println("Datos:  " + reportemanualGrupo);
			mAuxInvItem = em
					.createQuery(
							"select i  from AuxInvItem i join i.invGrupo g where g.gruCodigo = :grupo and i.iteEstado=true order by i.iteNombre")
					.setParameter("grupo", reportemanualGrupo).getResultList();
			for (AuxInvItem us : mAuxInvItem) {
				invAuxInvItem.add(new SelectItem(us.getIteCodigo(), us
						.getIteNombre()));
			}
			return invAuxInvItem;
		} else {

			return new ArrayList<SelectItem>();
		}
	}

	public Collection<SelectItem> getListaEgresoItemsSelectItems() {

		String varSqlitemsSeleccionado = "";

		if (auxInvItem != null)
			varSqlitemsSeleccionado = " and stock.iteCodigo<>'"
					+ auxInvItem.toUpperCase() + "'";

		Subdepartamento usuario = (Subdepartamento) Contexts
				.getSessionContext().get("usuarioLogeo");
		System.out.println(usuario.getDescripcion());
		Collection<SelectItem> invAuxInvItem = new ArrayList<SelectItem>();
		if (gruCodigo != null) {
			System.out.println("Datos:  " + gruCodigo);
			mAuxInvItemEgreso = em
					.createQuery(
							"select  stock from InvItemStock stock join stock.invGrupo g "
									+ "where g.gruCodigo = :grupo "
									+ " and stock.iteUnidad>0   "
									+
									/* varSqlitemsSeleccionado+ */
									" and  stock.subdepCodigo = :subdepartamento and stock.depCodigo = :departamento"
									+ " order by stock.iteNombre")
					.setParameter("grupo", this.gruCodigo).setParameter(
							"subdepartamento", usuario.getSubdepCodigo())
					.setParameter("departamento",
							usuario.getDepartamento().getDepCodigo())
					.getResultList();
			if (mAuxInvItemEgreso.size() > 0)
				invAuxInvItem.add(new SelectItem("", ""));
			for (InvItemStock us : mAuxInvItemEgreso) {
				invAuxInvItem.add(new SelectItem(us.getIteCodigo(), us
						.getIteNombre()));
			}
			return invAuxInvItem;
		} else {
			return new ArrayList<SelectItem>();
		}

	}

	public Collection<SelectItem> getListaRestriccionesSelectItems() {
		Collection<SelectItem> restricionItem = new ArrayList<SelectItem>();
		restricionItem.add(new SelectItem(" ", " "));
		restricionItem.add(new SelectItem("=", "="));
		restricionItem.add(new SelectItem("!=", "!="));
		restricionItem.add(new SelectItem("<", "<"));
		restricionItem.add(new SelectItem(">", ">"));
		restricionItem.add(new SelectItem(">=", ">="));
		restricionItem.add(new SelectItem("<=", "<="));
		return restricionItem;
	}

	public Collection<SelectItem> getListaMovimientosSelectItems() {
		Collection<SelectItem> movimientosItem = new ArrayList<SelectItem>();
		movimientosItem.add(new SelectItem(" ", " "));
		movimientosItem.add(new SelectItem("1", "Compras"));
		movimientosItem.add(new SelectItem("2", "Ventas"));
		movimientosItem.add(new SelectItem("3", "Saldos"));
		return movimientosItem;
	}

	public Collection<SelectItem> getTipoDeTransaccionSelectItems() {

		Collection<SelectItem> restricionItem = new ArrayList<SelectItem>();
		restricionItem.add(new SelectItem(" ", " "));
		restricionItem.add(new SelectItem("Egreso", "Egreso"));
		restricionItem.add(new SelectItem("Ingreso", "Ingreso"));
		return restricionItem;

	}

	public Collection<SelectItem> getTipoDeDatoSelectItems() {

		Collection<SelectItem> restricionItem = new ArrayList<SelectItem>();
		restricionItem.add(new SelectItem(" ", " "));
		restricionItem.add(new SelectItem("Precio", "Precio"));
		restricionItem.add(new SelectItem("Cantidad", "Cantidad"));
		return restricionItem;

	}

	public Collection<SelectItem> getListaEgresoItemsPorBodegaSelectItems() {
		long IdentificadoSubdepartamento = 0;
		Subdepartamento subdepartamento = new Subdepartamento();
		if (subdepartamento != null) {
			try {
				IdentificadoSubdepartamento = Long
						.parseLong(this.subdepartamento);
				subdepartamento = em.find(Subdepartamento.class,
						IdentificadoSubdepartamento);
			} catch (Exception e) {
				return new ArrayList<SelectItem>();
			}
			Collection<SelectItem> invAuxInvItem = new ArrayList<SelectItem>();
			if (gruCodigo != null) {
				System.out.println("Datos:  " + gruCodigo);
				mAuxInvItem = em
						.createQuery(
								"select i  from InvItemStock stock, AuxInvItem i join i.invGrupo g where g.gruCodigo = :grupo and i.iteEstado=1 and  stock.invGrupo=g.gruCodigo and stock.subdepCodigo = :subdepartamento and stock.depCodigo = :departamento"
										+ "order by i.iteNombre").setParameter(
								"grupo", this.gruCodigo).setParameter(
								"subdepartamento",
								subdepartamento.getSubdepCodigo())
						.setParameter(
								"departamento",
								subdepartamento.getDepartamento()
										.getDepCodigo()).getResultList();
				for (AuxInvItem us : mAuxInvItem) {
					invAuxInvItem.add(new SelectItem(us.getIteCodigo(), us
							.getIteNombre()));
				}
				return invAuxInvItem;
			} else {
				return new ArrayList<SelectItem>();
			}
		} else {
			return new ArrayList<SelectItem>();
		}
	}

	public List<String> metodoCalcularIntervalos(int n, Double[] varVarianza,
			Double[] varEsperanza) {

		double varIntervaloIncial = 0;
		double varIntervaloFinal = 0;
		double varIntervaloIncialSiguiente = 0;
		double varIntervaloFinalSiguiente = 0;
		String varInicial="";
		String varFinal="";
		List<String> varListadoDeIntervalo= new ArrayList<String>();
		for (int i = 0; i < varEsperanza.length; i++) {
			varIntervaloIncial = (varEsperanza[i] - (2 * varVarianza[i])
					/ (Math.sqrt(n)));
			varIntervaloFinal = (varEsperanza[i] + (2 * varVarianza[i])
					/ (Math.sqrt(n)));
			for (int j = 0; j < varEsperanza.length; j++) {
				varIntervaloIncialSiguiente = (varEsperanza[i] - (2 * varVarianza[i])
						/ (Math.sqrt(n)));
				varIntervaloFinalSiguiente = (varEsperanza[i] + (2 * varVarianza[i])
						/ (Math.sqrt(n)));

				// Si el intervalo se cruza con el anterio ;
				if ((varIntervaloIncialSiguiente != varIntervaloIncial)
						&& (varIntervaloFinalSiguiente != varIntervaloFinal)) {
					if ((varIntervaloIncial <= varIntervaloIncialSiguiente)
							&& (varIntervaloIncialSiguiente <= varIntervaloFinal)) {
						varInicial="L"+String.valueOf(i)+"["+
						String.valueOf(varIntervaloIncial)+" , "+String.valueOf(varIntervaloFinal)+"]";
						varFinal="L"+String.valueOf(j)+"["+
						String.valueOf(varIntervaloIncialSiguiente)+" , "+String.valueOf(varIntervaloFinalSiguiente)+"]";
						varListadoDeIntervalo.add(varInicial+" "+varFinal);
					}
				}

			}
		}
		
		// Retorna intervalos que se cruzan el size tiene que se mayor a 0 empate tecnico
		// Si size de la lisa es cero no se cruza 
		return varListadoDeIntervalo;

	}

	public Integer getCantidadSotck() {
		if (auxCodigo != null) {
			System.out.println("Datos:  " + auxCodigo);
			Subdepartamento usuario = (Subdepartamento) Contexts
					.getSessionContext().get("usuarioLogeo");
			List invItems = em
					.createQuery(
							"select i  from InvItemStock i where  i.iteCodigo = :codigo and i.subdepCodigo = :subdepartamento and i.depCodigo = :departamento")
					.setParameter("codigo", auxCodigo).setParameter(
							"subdepartamento", usuario.getSubdepCodigo())
					.setParameter("departamento",
							usuario.getDepartamento().getDepCodigo())
					.getResultList();
			if (invItems.size() > 0) {
				InvItemStock entidad = (InvItemStock) invItems.get(0);
				precio = entidad.getIteCosto();
				return entidad.getIteUnidad().intValue();
			}
		}
		return 0;
	}

	public BigDecimal getPrecioU() {
		return precio;
	}

	public BigDecimal getEgiCantidad() {
		return egiCantidad;
	}

	public BigDecimal getPrecioUPorCantidad() {

		if (getEgiCantidad() == null) {
			return new BigDecimal(0.0);
		} else {

			Integer varCantidad = getCantidadSotck();
			return getEgiCantidad().multiply(precio);
		}
	}

	public Collection<SelectItem> getListaProveedorSelectItems() {
		Collection<SelectItem> invProveedor = new ArrayList<SelectItem>();
		mInvProveedor = em.createQuery(
				"select p  from  InvProveedor p order by p.proNombre")
				.getResultList();

		if (mInvProveedor != null) {
			invProveedor.add(new SelectItem("", ""));
			for (InvProveedor us : mInvProveedor) {
				invProveedor.add(new SelectItem(us.getProCodigo(), us
						.getProNombre()));
			}
			return invProveedor;
		} else {

			return new ArrayList<SelectItem>();
		}
	}

	public Collection<SelectItem> getListaBusquedaDeProveedorSelectItems() {
		Collection<SelectItem> invProveedor = new ArrayList<SelectItem>();
		mInvProveedor = em.createQuery(
				"select p  from  InvProveedor p order by p.proNombre")
				.getResultList();

		if (mInvProveedor != null) {
			invProveedor.add(new SelectItem("", ""));
			for (InvProveedor us : mInvProveedor) {

				invProveedor.add(new SelectItem(String.valueOf(us
						.getProCodigo()), us.getProNombre()));
			}
			return invProveedor;
		} else {

			return new ArrayList<SelectItem>();
		}
	}

	public Collection<SelectItem> getListadoBusquedaGrupoSelectItems() {
		Collection<SelectItem> invGrupo = new ArrayList<SelectItem>();
		Integer contar = 0;
		mInvGrupo = em
				.createQuery(
						"select gt from InvGrupo gt where gt.gruEstado=true order by gt.gruNombre")
				.getResultList();
		invGrupo.add(new SelectItem("", ""));
		for (InvGrupo us : mInvGrupo) {
			invGrupo.add(new SelectItem(us.getGruCodigo(), us.getGruNombre()));
			contar++;
		}
		return invGrupo;
	}

	public Collection<SelectItem> getListadoBusquedaBodegaSelectItems() {
		Collection<SelectItem> subdepartamento = new ArrayList<SelectItem>();
		Integer contar = 0;
		mBodega = em.createQuery("select s from Subdepartamento s ")
				.getResultList();
		subdepartamento.add(new SelectItem("", ""));
		for (Subdepartamento us : mBodega) {
			subdepartamento.add(new SelectItem(String.valueOf(us
					.getSubdepCodigo()), us.getDescripcion()));
			contar++;
		}
		return subdepartamento;
	}

	public Collection<SelectItem> getListadoDepartamentosSelectItems() {
		Collection<SelectItem> subdepartamento = new ArrayList<SelectItem>();
		Integer contar = 0;
		mDepartamento = em.createQuery(
				"select d from Departamento d order by d.depDescripcion ")
				.getResultList();
		subdepartamento.add(new SelectItem("", ""));
		for (Departamento us : mDepartamento) {
			subdepartamento.add(new SelectItem(String
					.valueOf(us.getDepCodigo()), us.getDepDescripcion()));
			contar++;
		}
		return subdepartamento;
	}

	public Collection<SelectItem> getListadoBodegaSelectItems() {
		Collection<SelectItem> subdepartamento = new ArrayList<SelectItem>();
		Integer contar = 0;

		mBodega = em.createQuery(
				"select s from Subdepartamento s  order by s.descripcion")
				.getResultList();
		if (!mBodega.isEmpty()) {
			subdepartamento.add(new SelectItem(0, "Todos"));
			for (Subdepartamento us : mBodega) {
				subdepartamento.add(new SelectItem(us
						.getSubdepCodigo(), us.getDescripcion()));
				contar++;
			}
		} else {
			return new ArrayList<SelectItem>();
		}

		return subdepartamento;
	}

	public Collection<SelectItem> getListaBusquedaDeClienteSelectItems() {
		Collection<SelectItem> invClientes = new ArrayList<SelectItem>();
		mInvCliente = em.createQuery(
				"select p  from  InvCliente p order by p.cliNombre")
				.getResultList();

		if (mInvCliente != null) {
			invClientes.add(new SelectItem("", ""));
			for (InvCliente us : mInvCliente) {

				invClientes.add(new SelectItem(String
						.valueOf(us.getCliCodigo()), us.getCliNombre()));
			}
			return invClientes;
		} else {

			return new ArrayList<SelectItem>();
		}
	}

	/*
	 * Accessor used in the UI
	 */
	public Map<String, InvGrupo> getAllInvGrupo() {
		return mInvGrupoMap;
	}

	/*
	 * Get a converter initialized with the current list of types
	 */
	public Converter getConverter() {
		return new GadgetTypeConverter(mInvGrupo);
	}

	static public class GadgetTypeConverter implements Converter, Serializable {
		private List<InvGrupo> mTypes;

		public GadgetTypeConverter(List<InvGrupo> types) {
			this.mTypes = types;
		}

		public String getAsString(FacesContext ctx, UIComponent comp, Object obj) {
			if (obj == null)
				return null;

			InvGrupo type = (InvGrupo) obj;
			String val = type.getGruCodigo();

			return val;
		}

		public Object getAsObject(FacesContext ctx, UIComponent comp,
				String strVal) throws ConverterException {
			if (strVal == null || strVal.length() == 0) {
				return null;
			}

			String id = strVal;
			System.out.println(id);
			for (InvGrupo us : mTypes) {
				System.out.println(us.getGruCodigo());
				if (us.getGruCodigo().equals(id)) {
					return us;
				}
			}
			return null;
		}
	}

	@Remove
	@Destroy
	public void destroy() {
	}

}
